package cn.huaqingcheng.tianshu.core.auth.session;

import cn.huaqingcheng.tianshu.core.auth.jwt.JwtPayload;
import cn.huaqingcheng.tianshu.core.auth.jwt.JwtPayload.TokenType;
import cn.huaqingcheng.tianshu.core.auth.jwt.JwtService;
import cn.huaqingcheng.tianshu.core.auth.param.SimpleLoginParam;
import cn.huaqingcheng.tianshu.core.auth.view.LoginResponse;
import cn.huaqingcheng.tianshu.core.uc.model.Account;
import cn.huaqingcheng.tianshu.core.uc.model.AccountPassword;
import cn.huaqingcheng.tianshu.core.uc.service.AccountService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Service;

import java.util.Optional;

/**
 * SessionServiceImpl
 */
@Slf4j
@Service
@RequiredArgsConstructor
public class SessionServiceImpl implements SessionService {

    private final JwtService jwtService;

    private final AccountService accountService;

    private final PasswordEncoder encoder;


    @Override
    public LoginResponse login(SimpleLoginParam param) {
        String username = param.getUsername();

        Optional<Account> optional = accountService.getByUsername(username);
        if (optional.isEmpty()) {
            log.trace("用户名 {} 不存在", username);
            throw new IllegalArgumentException("用户名密码错误");
        }
        Account account = optional.get();
        String encodedPassword = Optional.ofNullable(account.getPassword())
                .map(AccountPassword::getCiphertext)
                .orElseThrow();

        boolean matches = encoder.matches(param.getPassword(), encodedPassword);
        if (!matches) {
            log.trace("密码错误");
            throw new IllegalArgumentException("用户名密码错误");
        }

        account.setPassword(null);
        Long accountId = account.getId();

        JwtPayload payload = new JwtPayload()
                .setType(TokenType.ACCESS)
                .setSubject(String.valueOf(accountId))
                .setAccountId(accountId);

        return new LoginResponse()
                .setAccess(jwtService.issued(payload))
                .setRefresh(jwtService.issued(payload.setType(TokenType.REFRESH)))
                .setAccount(account);
    }

}
